// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#ifndef CORE_FPDFAPI_PARSER_CPDF_HINT_TABLES_H_
#define CORE_FPDFAPI_PARSER_CPDF_HINT_TABLES_H_

#include <memory>
#include <vector>

#include "core/fpdfapi/parser/cpdf_data_avail.h"
#include "core/fxcrt/unowned_ptr.h"

class CFX_BitStream;
class CPDF_LinearizedHeader;
class CPDF_ReadValidator;
class CPDF_Stream;
class CPDF_SyntaxParser;

class CPDF_HintTables {
 public:
  struct SharedObjGroupInfo {
    FX_FILESIZE m_szOffset = 0;
    uint32_t m_dwLength = 0;
    uint32_t m_dwObjectsCount = 0;
    uint32_t m_dwStartObjNum = 0;
  };

  class PageInfo {
   public:
    PageInfo();
    ~PageInfo();

    void set_objects_count(uint32_t objects_count) {
      m_dwObjectsCount = objects_count;
    }
    uint32_t objects_count() const { return m_dwObjectsCount; }

    void set_page_offset(FX_FILESIZE offset) { m_szOffset = offset; }
    FX_FILESIZE page_offset() const { return m_szOffset; }

    void set_page_length(uint32_t length) { m_dwLength = length; }
    uint32_t page_length() const { return m_dwLength; }

    void set_start_obj_num(uint32_t start_obj_num) {
      m_dwStartObjNum = start_obj_num;
    }
    uint32_t start_obj_num() const { return m_dwStartObjNum; }

    void AddIdentifier(uint32_t Identifier) {
      m_dwIdentifierArray.push_back(Identifier);
    }

    const std::vector<uint32_t>& Identifiers() const {
      return m_dwIdentifierArray;
    }

   private:
    uint32_t m_dwObjectsCount = 0;
    FX_FILESIZE m_szOffset = 0;
    uint32_t m_dwLength = 0;
    uint32_t m_dwStartObjNum = 0;
    std::vector<uint32_t> m_dwIdentifierArray;

    PageInfo(const PageInfo& other) = delete;
    PageInfo& operator=(const PageInfo&) = delete;
  };

  static std::unique_ptr<CPDF_HintTables> Parse(
      CPDF_SyntaxParser* parser,
      const CPDF_LinearizedHeader* pLinearized);

  CPDF_HintTables(CPDF_ReadValidator* pValidator,
                  const CPDF_LinearizedHeader* pLinearized);
  virtual ~CPDF_HintTables();

  bool GetPagePos(uint32_t index,
                  FX_FILESIZE* szPageStartPos,
                  FX_FILESIZE* szPageLength,
                  uint32_t* dwObjNum) const;

  CPDF_DataAvail::DocAvailStatus CheckPage(uint32_t index);

  bool LoadHintStream(CPDF_Stream* pHintStream);

  const std::vector<PageInfo>& PageInfos() const { return m_PageInfos; }
  const std::vector<SharedObjGroupInfo>& SharedGroupInfos() const {
    return m_SharedObjGroupInfos;
  }

  FX_FILESIZE GetFirstPageObjOffset() const { return m_szFirstPageObjOffset; }

 protected:
  bool ReadPageHintTable(CFX_BitStream* hStream);
  bool ReadSharedObjHintTable(CFX_BitStream* hStream, uint32_t offset);

 private:
  FX_FILESIZE HintsOffsetToFileOffset(uint32_t hints_offset) const;

  uint32_t m_nFirstPageSharedObjs = 0;
  FX_FILESIZE m_szFirstPageObjOffset = 0;
  std::vector<PageInfo> m_PageInfos;
  std::vector<SharedObjGroupInfo> m_SharedObjGroupInfos;
  UnownedPtr<CPDF_ReadValidator> m_pValidator;
  UnownedPtr<const CPDF_LinearizedHeader> const m_pLinearized;
};

#endif  // CORE_FPDFAPI_PARSER_CPDF_HINT_TABLES_H_
`CPDF_HintTables` 类及其内部类 `PageInfo` 提供了处理 PDF 文档中的线性化提示表的功能。以下是该接口的功能列表：

### CPDF_HintTables 类

#### 公共方法
1. * *static std::unique_ptr<CPDF_HintTables> Parse(CPDF_SyntaxParser * parser, const CPDF_LinearizedHeader * pLinearized) * *: 解析器，用于创建 `CPDF_HintTables` 对象。
2. * *CPDF_HintTables(CPDF_ReadValidator * pValidator, const CPDF_LinearizedHeader * pLinearized) * *: 构造函数，用于初始化提示表。
3. * *virtual ~CPDF_HintTables() * *: 析构函数。
4. * *bool GetPagePos(uint32_t index, FX_FILESIZE * szPageStartPos, FX_FILESIZE * szPageLength, uint32_t * dwObjNum) const** : 获取指定页面的位置信息。
5. * *CPDF_DataAvail::DocAvailStatus CheckPage(uint32_t index) * *: 检查页面是否可用。
6. * *bool LoadHintStream(CPDF_Stream * pHintStream) * *: 加载提示流。
7. * *const std::vector<PageInfo>&PageInfos() const** : 获取所有页面信息。
8. * *const std::vector<SharedObjGroupInfo>&SharedGroupInfos() const** : 获取所有共享对象组信息。
9. * *FX_FILESIZE GetFirstPageObjOffset() const** : 获取第一页对象的偏移量。

#### 保护方法
10. * *bool ReadPageHintTable(CFX_BitStream * hStream) * *: 读取页面提示表。
11. * *bool ReadSharedObjHintTable(CFX_BitStream * hStream, uint32_t offset) * *: 读取共享对象提示表。

#### 私有方法
12. * *FX_FILESIZE HintsOffsetToFileOffset(uint32_t hints_offset) const** : 将提示偏移转换为文件偏移。

### CPDF_HintTables::PageInfo 内部类

#### 公共方法
1. * *PageInfo() * *: 构造函数。
2. * *~PageInfo() * *: 析构函数。
3. * *void set_objects_count(uint32_t objects_count) * *: 设置对象数量。
4. * *uint32_t objects_count() const** : 获取对象数量。
5. * *void set_page_offset(FX_FILESIZE offset) * *: 设置页面偏移量。
6. * *FX_FILESIZE page_offset() const** : 获取页面偏移量。
7. * *void set_page_length(uint32_t length) * *: 设置页面长度。
8. * *uint32_t page_length() const** : 获取页面长度。
9. * *void set_start_obj_num(uint32_t start_obj_num) * *: 设置起始对象编号。
10. * *uint32_t start_obj_num() const** : 获取起始对象编号。
11. * *void AddIdentifier(uint32_t Identifier) * *: 添加标识符。
12. * *const std::vector<uint32_t>&Identifiers() const** : 获取标识符列表。

这些功能共同提供了对 PDF 文档中线性化提示结构的解析与管理能力，有助于实现快速页面访问和共享对象管理。